from datetime import datetime

from django.db.models import Sum
from django.db.utils import IntegrityError

from organization.models import (BusinessDept, BusinessLine)
from record.models import (BusinessCostRecord, IncomeRecord, Salary)
from report.models import (BusinessLineMonthlyReport,
                           BusinessLineAccReport, BusinessDeptMonthlyReport, BusinessDeptAccReport)


def report(begin_time:datetime=None, end_time:datetime=None, **kwargs):
    human_cost = Salary.objects.filter(**kwargs)
    income = IncomeRecord.objects.filter(**kwargs)
    business_cost = BusinessCostRecord.objects.filter(**kwargs)

    if begin_time:
        human_cost = human_cost.filter(pay_date__gte=begin_time)
        income = income.filter(date__gte=begin_time)
        business_cost = business_cost.filter(date__gte=begin_time)

    if end_time:
        human_cost = human_cost.filter(pay_date__lt=end_time)
        income = income.filter(date__lt=end_time)
        business_cost = business_cost.filter(date__lt=end_time)

    rst = [human_cost.aggregate(human_cost=Sum('company_pay_total'))['human_cost'],
    income.aggregate(income=Sum('income'))['income'],
    business_cost.aggregate(business_cost=Sum('cost'))['business_cost']]

    return map(lambda x: x if x is not None else 0, rst) #human_cost, business_cost, income


def bline_month_report(begin_time, end_time):

    for bline in BusinessLine.objects.all():
        try:
            human_cost, business_cost, income = report(begin_time, end_time, businessline=bline)
            blmr = BusinessLineMonthlyReport()
            blmr.human_cost = human_cost
            blmr.business_cost = business_cost
            blmr.income = income
            blmr.total_cost = human_cost + business_cost
            blmr.total_income = income - (human_cost + business_cost)
            blmr.month = begin_time
            blmr.businessline = bline
            blmr.businessdept = bline.businessdept
            blmr.save()
        except IntegrityError as e:
            if str(e).startswith('UNIQUE'):
                # UNIQUE constraint failed
                pass
            else:
                raise e

        try:
            human_cost, business_cost, income = report(end_time=end_time, businessline=bline)
            blar = BusinessLineAccReport()
            blar.human_cost = human_cost
            blar.business_cost = business_cost
            blar.income = income
            blar.total_cost = human_cost + business_cost
            blar.total_income = income - (human_cost + business_cost)
            blar.month = begin_time
            blar.businessline = bline
            blar.businessdept = bline.businessdept
            blar.save()
        except IntegrityError as e:
            if str(e).startswith('UNIQUE'):
                # UNIQUE constraint failed
                pass
            else:
                raise e


def bdept_month_report(begin_time, end_time):

    for bdept in BusinessDept.objects.all():
        try:
            human_cost, business_cost, income = report(begin_time, end_time, businessdept=bdept)

            bdmr = BusinessDeptMonthlyReport()
            bdmr.human_cost = human_cost
            bdmr.business_cost = business_cost
            bdmr.income = income
            bdmr.total_cost = human_cost + business_cost
            bdmr.total_income = income - (human_cost + business_cost)
            bdmr.month = begin_time
            bdmr.businessdept = bdept
            bdmr.save()

            print(bdmr.month)
        except IntegrityError as e:
            if str(e).startswith('UNIQUE'):
                # UNIQUE constraint failed
                pass
            else:
                raise e

        try:
            human_cost, business_cost, income = report(end_time=end_time, businessdept=bdept)
            bdar = BusinessDeptAccReport()
            bdar.human_cost = human_cost
            bdar.business_cost = business_cost
            bdar.income = income
            bdar.total_cost = human_cost + business_cost
            bdar.total_income = income - (human_cost + business_cost)
            bdar.month = begin_time
            bdar.businessdept = bdept
            bdar.save()
        except IntegrityError as e:
            if str(e).startswith('UNIQUE'):
                # UNIQUE constraint failed
                pass
            else:
                raise e
